热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

句子|语料_快速构建一个简单的对话+问答AI(上)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了快速构建一个简单的对话+问答AI(上)相关的知识,希望对你有一定的参考价值。文章目录

篇首语:本文由编程笔记#小编为大家整理,主要介绍了快速构建一个简单的对话+问答AI (上)相关的知识,希望对你有一定的参考价值。



文章目录


  • 前言
  • part0 资源准备
    • 基本功能
    • 语料
      • 停用词
      • 问答
      • 闲聊语料

    • 获取

  • part01句的表达
    • 表达
      • one-hot编码

    • 词嵌入
        • 大致原理
        • 实现
          • 简单版
          • 复杂版
            • 如何训练



      • 转换后的形状


  • part02 循环神经网络
    • RNN
      • RNN投影图
      • RNN是三维立体的

    • LSTM&GRU

  • part03意图识别
    • 分词
    • FastText分类
      • FastText网络结构
      • 优化点

    • 构造FastText数据集
    • 训练

  • part04 闲聊对话
    • Seq2Seq
      • 网络结构
      • 输入与输出(编/解码器)

    • 数据准备
      • 构造词典
      • 数据加载

    • 网络搭建
      • 编码器
      • 解码器
      • 注意力机制

    • 训练
      • 搭建seq网络
      • 训练

    • 推理
      • BeamSearch
      • 完整过程


  • Part05 问答处理
    • 简单思路
    • 难点

  • 上文分割线


前言

okey,许久不见甚是想念,那么今天的话也是来开启一个新的一个章节吧。当然承认最近是有在划水,但是问题不大。那么今天的话咱们就是来填一填以前的坑,吹过的牛皮总还是要实现的。那么在这边咱们的目的是实现出一个简单一点的AI助手,通过我们的文本来实现一些对话,问答之类的一些处理。从基础部分,一步一步实现一个这样的小AI,在未来你还可以打造属于自己的一个数据集,同时在这个架构的基础上不断优化,在未来的某一天也许是有机会得到一个专属于你的一个AI对象的。

所以咱们今天给出的还是一个baseline。同时本文的风格也是慢慢来递进的,从最基础的尺度表达,到搭建一个网络,再到基本的优化,最后是一个封装。
项目开源地址:
https://github.com/Huterox/xiaojiejieBoot.git

咱们的这个机器人就叫叫作“小姐姐”。是的非常的直接:Although I have been rejected, I will not give up.
对应语料资源:
https://github.com/codemayq/chinese_chatbot_corpus

基本要求,阅读本篇文章需要一定的门槛:


  • 熟练掌握python
  • 了解基本的深度学习知识
  • 会使用pytorch搭建神经网络
  • 具备一定的抽象能力(受限于篇幅问题,本博文在原理部分只能做简化,因此重点还是实战(或者说,都在代码里面了),但是对应相应内容都会进行一个介绍,和我认为比较容易不太好理解的点,所以如果想要完善理论部分的话,建议自行深入,这里更多是科普,之后是代码实现,你将这部分作为灰盒子就好了,因为你还是可以调参,准备自己的数据集的)

part0 资源准备

ok,在开始之前呢,咱们先来说说在咱们本篇博文当中,咱们是怎么设计的,需要使用到哪些资源。


基本功能

先来看到咱们的这个基本功能的一个样例图吧:

所以的话,咱们这边有问答功能,和闲聊功能,现在的话,那么闲聊的话其实顾名思义,其实就是说如果你想要让这个AI能够就是说像情侣一样对话的话,那么这个闲聊就是咱们的这个恋爱聊天功能,也就是所谓的AI女友的最基本的一个对话雏形。


语料

ok,看到了咱们的一个具体的大致的功能,那么咱们接下来要做的就是说,我们需要使用到哪些东西。首先的话,由于咱们只是先做一个baseline级别的dome,加上咱们的这个算力确实比较那啥。所以的话,咱们的这个语料都是做了一个简要的删减,因为确实是太多了。
那么首先咱们这边使用的主要是这四个东西:

首先第一个是百度问答的问答对一共是5W,还有小黄鸡的一个语料库,大概是50W条问答。
之后第百度停用词和汉语词库。大概就这几个。那么如果你是想要做AI情侣的话,那么就需要把小黄鸡的一个语料库,换成这个对应的恋爱对话的一个语料(你可以尝试把你和你对象的对话搞过来,但是量得足够大,那么咱们这边就不去搞这种,一方面是我搞不到这个数据集,也没有没有办法从自己身上收集,另一方面确实不太合适,但是方法我还是会说的)

之后的话,咱们来看看一看咱们的这个格式:


停用词

打开之后的话,格式大概是这样的:

词库的格式也是类似的。


问答

之后的是问答的一个语料,这个是百度的一个问答,通过数据处理之后的一个格式。这边整理好了。格式是这样的:

问答对。


闲聊语料

这个闲聊也简单,是这样的:

E 是开始标志
M 对话

这个到时候怎么用,咱们在后面再说。


获取

之后的话是咱们的一个资源的获取。
这块的资源的话都已经打包好了在这:
链接:https://pan.baidu.com/s/1Bb0sWcITQLrkibDqIT8Qvg
提取码:6666


part01句的表达

表达

计算机和我们人类是不一样的,他只能进行基本的数字运算,在咱们先前的图像处理当中,图像的表达依然还是通过数值矩阵的,但是一个句子或者单纯是如何表示的呢。所以为了能够让计算机可以处理到咱们的文本数据,咱们需要对文本做一点点处理。

那么在这里是如何做的呢,其实很简单,既然计算机只能处理数字,对数字进行运算,那么我们只需要把我们的一个句子转化为一种向量就好了。那么这个是如何做的呢?

其实非常简单。

看下面一组图就明白了:

我们通过一个词典其实就可以完成一个向量的映射。

看到了吧,我们这个时候我们只需要对一个句子进行分词,之后将每一个词进行标号,这样一来就可以实现把一个句子转化为一个向量。


one-hot编码

此时我们得到了一组序列,但是这个序列的表达能力是在是太弱了,只能表示出一个标号,不能表示出其他的特点。或者说,只有一个数字表示一个词语实在是太单调了,1个词语也应该由一个序列组成。那么这个时候one-hot编码就出来了。他是这样做的:

首先一个词,一个字,我们叫做token,那么编码的很简单。其实就是这样:

但是这样是有问题的,那就是说,我们虽然实现了一个词到向量的表示。但是这个表示方法显然是太大了,假设有10000个词语,那么按照这种方式进行标号的话,那么1个词就是10000个维度。这样显然是不行的。所以这块需要优化一下。


词嵌入

这个原来解释起来稍微复杂一点。你只需要需要知道他们的本质其实就是这样的:
词 ——> 向量空间1 ——> 向量空间2
现在向量空间1不合适,所以我们要想办法能不能往空间2进行靠拢。

于是乎这里大概就有了两个方案:



1)尝试将词向量映射到一个更低维的空间;
2)同时保持词向量在该低维空间中具备语义相似性,如此,越相关的词,它们的向量在这个低维空间里就能靠得越近。


对于第一个,咱们可以参考原来咱们做协同过滤推荐dome的时候,使用SVD矩阵分解来做。(关于这篇博文的话也是有优化的,优化方案将在本篇博文中查看到,先插个眼)

那么缺点的话也很明显嘛,用咱们的这个方案:



1)亲和矩阵的维度可能经常变,因为总有新的单词加进来,每加进来一次就要重新做SVD分解,因此这个方法不太通用;
2)亲和矩阵可能很稀疏,因为很多单词并不会成对出现。



大致原理

ok,回到咱们的这个(这部分可以选择跳过,知道这个玩意最后得到的是啥就好了),这个该怎么做,首先的话,实现这个东西,大概是有两种方案去做:Continuous Bag Of Words (CBOW)方法和n-gram方法。第一个方案的话,这个比较复杂,咱们这里就不介绍了。

咱们来说说第二个方案。

首先咱们来说说啥是N-gram,首先原理的话也是比较复杂的,具体参考这个:https://blog.csdn.net/songbinxu/article/details/80209197

那么我们这边就是简单说一下这个在咱们这边N-gram实际是咋用的。

[cuted[i:i+2]for i in range(len(cuted))]

其实就是这个,用代码表示,cuted是一个分好词的句子。i+2表示跨越几个。

这样做的好处是,通过N-gram可以考虑到词语之间的一个关系,如果我们使用这个方案来实现一个词向量的话,那么我们必然是可以能够实现:“同时保持词向量在该低维空间中具备语义相似性,如此,越相关的词,它们的向量在这个低维空间里就能靠得越近。”的。因为确实考虑到了之间的一个关系,那么现在我们已经知道了大概N-garm是怎么样的了,其实就是一种方式,将一个句子相近的词语进行连接,或者说是对句子进行一个切割,上面那个只是一种方式只有,这个我们在后面还会有说明,总之它是非常好用的一种方式。

ok,知道了这个我们再来介绍几个名词:



1.跳词模型
跳词模型,它是通过文本中某个单词来推测前后几个单词。例如,根据‘rabbit’来推断前后的单词可能为‘a’,‘is’,‘eating’,‘carrot’。在训练模型时我们在文本中选取若干连续的固定长度的单词序列,把前后的一些单词作为输出,中间的某个位置的单词作为输入。




2.连续词袋模型
连续词袋模型与跳词模型恰好相反,它是根据文本序列中周围单词来预测中心词。在训练模型时,把序列中周围单词作为输入,中心词作为输出。


这个的话其实和我们的这个关系不大,因为N-gram其实是句子–>词 的一种方式,但是对我训练的时候的输入还是有帮助的,因为这样输入的话,我们是可以得到词在句子当中的一种关联关系的。

而embedding是词到one-hot然后one-hot到低纬向量的变化过程。


实现

ok,扯了那么多,那么接下来看看我们如何实现这个东西。

我们需要一个词向量,同时我们有很多词语,因此我们将得到一个矩阵,这个矩阵叫做embedding矩阵。

我们首先随机初始化embeddings矩阵,构建一个简单的网络。初始化weights和biases,计算隐藏层的输出。然后计算输出和target结果的交叉熵,之后使用优化器完成一次反向传递,更新可训练的参数,包括embeddings变量。并且我们将词之间的相似度可以看作概率。

ok,我们直接看到代码,那么咱们也是有两个版本的。简单版,复杂版。


简单版

简单版本的话,在pytorch当中有实现:

embed=nn.Embedding(word_num,embedding_dim)

复杂版

那么我们显然是不满足这个的,那么我们还有复杂版本。就是自己动手,丰衣足食!
首先我们定义这个:

class embedding(nn.Module):
def __init__(self,in_dim,embed_dim):
super().__init__()
self.embed=nn.Sequential(nn.Linear(in_dim,200),
nn.ReLU(),
nn.Linear(200,embed_dim),
nn.Sigmoid())
def forward(self,input):
b,c,_=input.shape
output=[]
for i in range(c):
out=self.embed(input[:,i])
output.append(out.detach().numpy())
return torch.tensor(np.array(output),dtype=torch.float32).permute(1,0,2)

很简单的一个结构。
那么我们输入是上面,首先其实是我们one-hot编码的一个矩阵。
我们其实流程就是这样的:词—>one-hot—>embedding/svd

ok,那么我们的N-gram如何表示呢,其实这个更多的还是在于对句子的分解上,输入的句子的词向量如何表示的。


如何训练

如何训练的话,首先还是要在one-hot处理的时候再加一个处理,这个过程可能比较绕。就是说我们按照上面提到的词袋模型进行构造我们的数据,我们举个例子吧。

现在有这样的一个文本,分词之后,词的个数是content_size。有num_word个词。

import torch
import re
import numpy as np

txt=[] #文本数据
with open('peter_rabbit.txt',encoding='utf-8') as f:
for line in f.readlines():
l=line.strip()
spilted_sentence=re.split(" |;|-|,|!|\\'",l)
for w in spilted_sentence:
if w !='':
txt.append(w.lower())
vol=list(set(txt)) #单词表
n=len(vol) #单词表单词数
vol_dict=dict(zip(vol,np.arange(n))) #单词索引
'''
这里使用词袋模型
每次从文本中选取序列长度为9,输入单词数为,8,输出单词数为1,
中心词位于序列中间位置。并且采用pytorch中的emdedding和自己设计embedding两种方法
词嵌入维度为100。
'''

data=[]
label=[]

for i in range(content_size):
in_words=txt[i:i+4]
in_words.extend(txt[i+6:i+10])
out_word=txt[i+5]
in_one_hot=np.zeros((8,n))
out_one_hot=np.zeros((1,n))
out_one_hot[0,vol_dict[out_word]]=1
for j in range(8):
in_one_hot[j,vol_dict[in_words[j]]]=1
data.append(in_one_hot)
label.append(out_one_hot)

class dataset:
def __init__(self):
self.n=ci=config.content_size
def __len__(self):
return self.n
def __getitem__(self, item):
traindata=torch.tensor(np.array(data),dtype=torch.float32)
trainlabel=torch.tensor(np.array(label),dtype=torch.float32)
return traindata[item],trainlabel[item]

我们只是在投喂数据的时候按照词袋模型进行投喂,或者连续模型也可以。

当然我们这里所说的都只是说预训练出一个模型出来,实际上,我们直接使用这个结构,然后进行正常的训练完成我们的一个模型也是可以的。她是很灵活的,不是固定的!

那么继续预训练的话就是按照词袋模型来就好了(看不懂没关系,跳过就好了)

import torch
from torch import nn
from torch.utils.data import DataLoader
from dataset import dataset
import numpy as np
class model(nn.Module):
def __init__(self):
super().__init__()
self.embed=embedding(num_word,100)
self.fc1=nn.Linear(num_word,1000)
self.act1=nn.ReLU()
self.fc2=nn.Linear(1000,num_word)
self.act2=nn.Sigmoid()
def forward(self,input):
b,_,_=input.shape
out=self.embed (input).view(b,-1)
out=self.fc1 (out)
out=self.act1(out)
out=self.fc2(out)
out=self.act2(out)
out=out.view(b,1,-1)
return out
if __name__=='__main__':
pre_model=model()
optim=torch.optim.Adam(params=pre_model.parameters())
Loss=nn.MSELoss()
traindata=DataLoader(dataset(),batch_size=5,shuffle=True)
for i in range(100):
print('the epoch'.format(i))
for d in traindata:
p=model(d[0])
loss=Loss(p,d[1])
optim.zero_grad()
loss.backward()
optim.step()

这样一来就可以初步完成预训练,你只需要加载好embeding部分的权重就好了,这个只是加快收敛的一种方式。


转换后的形状

最终,词嵌入的话,得到的矩阵是将one-hot变化为了这样的矩阵

ok,词的表达已经🆗了,那么接下来我们在简单介绍一下RNN。
(当然对于这一部分,实际上的话其实还有别的方法,但是咱们这边只是用到这些东西,所以只是介绍这个)


part02 循环神经网络

RNN

这个RNN的话,咋说呢,其实挺简单的,但是有几个点可能是比较容易误导人的,搞清楚这个结构的话,对于我们后面对于LSTM,GRU这种网络的架构可能会更好了解,其实包括LSTM,GRU的话其实本质上还是挺简单的。当然能够直接提出这个东西的人是非常厉害的,不过不管怎么说他们都是属于循环神经网络的一个大家族的,只是在数据处理上面多了一点点东西。那么理解了RNN之后的话,对于我后面理解LSTM,GRU里面它的一个数据的变幻,传递,原理。因为后面的话,我们还是要手写实现这个GRU的(LSTM也是一样的,但是GRU少了点参数,消耗的计算资源少一点点)。所以对于这一部分还是有必要好好唠一唠的。

首先我们来看到基本的神经网络:

这是一个简单的前馈神经网络,也是我们最常见的神经网络。

接下来是我们的RNN神经网络,在大多数情况下,我们经常会提到这几个名词:时间步,最后一层输出等等。

那么在这里的话,我们需要理解展开的其实只有一个东西,那就是对应时间步的理解,什么是上一层网络的输出,他们之间的参数是如何传递的。


RNN投影图

那么在此之前,我们先来看看RNN的网络结构大概是什么样子的。
大多数情况下,你搜索到的图片可能是这样的:

首先承认这张图非常的简洁,以至于你可能一开始没有反应过来,什么体现循环,体现时间步的地方在哪。其实这里的话,这种图其实只是一个缩略平面图。


RNN是三维立体的

但是实际上,如果需要用画图来表示的话,RNN其实是立体的一个样子。大概长这个样子:

可能有点抽象,但是它的意思其实就是这样的,这个其实是RNN真正的样子,之后通过对不同的时间步的输出进行不同的处理,最终我们还可以将RNN进行分类。

OK,这个就是我们在RNN里面需要注意的点,它的真实结构是这样的,是一个三维度的结构。同样的接下来要提到的LSTM,GRU都是。

OK,接下来还没完,我们现在需要不目光放长远一点,首先是在RNN里面对于层的概念,我们接下来会说什么什么层,搭建几层的一个LSTM,GRU之类的,或者说几层的RNN,这个层其实是指,一个时间步上有几个立体的层,而不是说先前平面的那种网络,说几层几层。因为实际上,咱们这里图画的就一层全连接(输入层不算),但是在时间步上,它是N层,你有几个X就有几个层。

我们拿一个句子为例,假设一句话有5个单词,或者说处理之后有5个词语。那么RNN就是把每一个词的词向量作为输入,按照顺序,按照上面图的顺序进行输入。此时需要做的就是循环5次。


LSTM&GRU

那么之后的话,咱们再来说说LSTM和GRU,他们呢叫做长短期记忆网络,其实就是最low的RNN的一个升级版,对信息进一步处理。我们对于模型的调优,优化说白了,除了性能的优化,就是对信息的最大利用(增加信息,或者对重点信息进行提取)。所以基本上为什么大模型的效果很好,其实不考虑对信息的利用率,单单是对信息的使用就已经达到了超大的规模,这效果肯定是比小模型好一点的。

那么这里的话,我们就简单过一下这个结构图吧。

首先是LSTM,其实的话他这里主要是引入了一个东西,叫做记忆。

c就是记忆,因为刚刚的RNN,的话其实更像是一个一阶的马尔科夫,那么导入这个的话,就相当于日记,你不仅仅知道了昨天做了什么,还知道了前天做了什么,这样的话对于信息的利用坑定是上去了的。那么这个是它的一个单元。
宏观上还是这样的:

同理GRU也是一样的

但是这里的话少了一个c 其实还是说把Ht和c合在了一起,他们效果是差不多的,各有各的好处,你用LSTM还能多得到一个日记本,用GRU的话其实相当于,你把日记写在了脑子里面。好处是省钱,坏处是有时候要你女朋友可能需要检查日记(虽然我知道你有95%以上的概率是没有的,一般设置0.05 作为阈值,低于这个概率,基本上我们认为G了)


part03意图识别

OK,我们终于到了写代码的地方了,首先我们这边有三个任务,第一个我们要知道,用户输入的想法意图是什么。所以我们这边需要搞一个文本分类的网络。之后的话,我们就是对话和问答。这里比较难的其实就是闲聊部分。在这部分的话我们还需要学会如何手写GRU的循环过程,为什么用GRU前面说了哈(省点资源,也木有女朋友查“日记”的需求,因为没有)。


分词

那么我们首先要做的就是分词
重点是为了后面能够对这两个家伙实现分词:

ok,那么我们先进行分词,首先是要加载咱们的词典以及咱们的这个停用词,这样的话方便提高效果。
那么在这边的话在这:

这里先进行初始化,加载对应的词典之类的

import jieba
import jieba.posseg as pseg
from tqdm import tqdm, trange
from config.config import jieba_config
import string
jieba.load_userdict(jieba_config.get("word_dict"))
jieba = jieba
pseg = pseg
string = string
with open(file=jieba_config.get("stop_dict"),encoding='utf-8') as f:
lines = tqdm(f.readlines(),desc="loading stop word")
StopWords = .fromkeys([line.rstrip() for line in lines ])
print("\\033[0;32;40m all loading is finished!\\033[0m")
__all__ = ['string','jieba','StopWords','pseg']

之后的话分词就好了:

"""
this model just for cutting words
"""

import utils
class Cut(object):
def __init__(self,other_letters=None):
self.letters = utils.string.ascii_letters
self.stopword = utils.StopWords
def __stop_not_sign(self,result):
result_rel = []
for res in result:
if (res not in self.stopword):
result_rel.append(res)
return result_rel
def __stop_with_sign(self, result):
result_rel = []
for res in result:
if (res.word not in self.stopword):
result_rel.append((res.word,res.flag))
return result_rel
def cut(self,sentence,by_word=False,
use_stop_word=False,with_sg=False
):
"""
:param sentence:
:param by_word:
:param use_stop_word:
:param with_sg:
:return:
"""

if(by_word):
return self.cut_sentence_by_word(sentece)
else:
'''
without by word,so there will be cutting by jieba
'''

if (with_sg):
result = utils.pseg.lcut(sentece)
if(use_stop_word):
result = self.__stop_with_sign(result)
else:
result = utils.jieba.lcut(sentece)
if (use_stop_word):
result = self.__stop_not_sign(result)
return result
def cut_sentence_by_word(self,sentence):
"""
it can cut English sentences and Chinese
:param sentence:
:return:
"""

result = []
temp = ""
for word in sentence:
if word.lower() in self.letters:
temp+=word
else:
if(temp!=""):
result.append(temp)
temp = ""
else:
result.append(word.strip())
if(temp!=""):
result.append(temp.lower())
return result
if __name__ == '__main__':
sentece = "你好呀Hello Word?"
cut = Cut()
print(cut.cut(sentece,by_word=False,use_stop_word=True,with_sg=False))

在这里的话就实现了一个简单的句子分词,之后我们还需要使用到这个工具类。


FastText分类

OK,我们快步进入到咱们的FastText,这个东西呢,其实是FaceBook推出的一个能够快速训练文本分类的一个工具模型。我们只需要按照它的格式来输入创建数据集就好了,就可以实现出一个分类效果,这样的话对于我们后面的作用是非常大的。

直接:

pip install fasttext

即可完成安装。

那么同样的在使用之前的话,我简要介绍一下FastText。


FastText网络结构

首先FastText的话其实是非常简单的一个模型


优化点

就是这样的一个结构,其实和很多手写LSTM文本分类的例子很像。但是它的优化点在于:
在使用方面,支持并行计算,可以节省训练时间。
在算法方面:


  1. 使用N-gram 的方式进行处理(当然我们这边其实也是,只是我们这边N=1)
  2. 通过哈夫曼树进行层次化softmax 优化最后计算概率

那么我们这里简单说一下这个层次化softmax。其实这玩意的本质其实就是在玩概率组合。
首先我们通过哈夫曼树,将对应的标签构造出一棵树。

每次,把多分类的softmax变成了二分类的,此时你甚至可以直接使用sigmod代替softmax函数。

ok,这个做一个了解即可。我们继续我们的编码。


构造FastText数据集

那么接下来我们需要构建FastText需要的数据。
我们需要的数据的集合的格式是这样的:

当然这个格式其实也是可以进行修改的,
这个的话在fastText源码当中可以看到

那么这个的话我这里就不解释了,我们直接上代码:

"""
this mode for preparing data which fasttext need
"""

from tqdm import tqdm, trange
from config import config
from utils.cut_word import Cut
import json
class process_classfiy(object):
def __init__(self):
self

推荐阅读
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文介绍了Foundation框架中一些常用的结构体和类,包括表示范围作用的NSRange结构体的创建方式,处理几何图形的数据类型NSPoint和NSSize,以及由点和大小复合而成的矩形数据类型NSRect。同时还介绍了创建这些数据类型的方法,以及字符串类NSString的使用方法。 ... [详细]
  • mui框架offcanvas侧滑超出部分隐藏无法滚动如何解决
    web前端|js教程off-canvas,部分,超出web前端-js教程mui框架中off-canvas侧滑的一个缺点就是无法出现滚动条,因为它主要用途是设置类似于qq界面的那种格 ... [详细]
  • 老牌医药收割AI红利:先投个15亿美元抢中国人才
    萧箫发自凹非寺量子位报道|公众号QbitAI没想到,一场大会把我的“刻板印象”攻破了。2021世界人工智能大会现场,能看见不少熟悉的身影, ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • EPPlus绘制刻度线的方法及示例代码
    本文介绍了使用EPPlus绘制刻度线的方法,并提供了示例代码。通过ExcelPackage类和List对象,可以实现在Excel中绘制刻度线的功能。具体的方法和示例代码在文章中进行了详细的介绍和演示。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 在工作了一年多后,我对现在的工作感到厌倦,没有激情,于是决定转行做程序猿。我在学校开了一个某宝店,通过自己摸索和努力,每个月挣够了零花钱和伙食费。我决定往互联网方向靠,不喜欢面对面和人沟通,而虚拟世界中的开发工作让我感到兴奋。我开始学习Java,感到困惑和怀疑自己的智商,但一篇鸡汤文激发了我学习Python的兴趣,我感到智商找回来了。我相信没有梦想的人和咸鱼没有什么区别。 ... [详细]
  • 本文介绍了在Ubuntu 11.10 x64环境下安装Android开发环境的步骤,并提供了解决常见问题的方法。其中包括安装Eclipse的ADT插件、解决缺少GEF插件的问题以及解决无法找到'userdata.img'文件的问题。此外,还提供了相关插件和系统镜像的下载链接。 ... [详细]
  • 本文介绍了在无法联网的情况下,通过下载rpm包离线安装zip和unzip的方法。详细介绍了如何搜索并下载合适的rpm包,以及如何使用rpm命令进行安装。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 校园表白墙微信小程序,校园小情书、告白墙、论坛,大学表白墙搭建教程
    小程序的名字必须和你微信注册的名称一模一样在后台注册好小程序。mp.wx-union.cn后台域名https。mp.wx-union.cn ... [详细]
author-avatar
mobiledu2502863117
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有